/**
 * @file test5.cpp
 * @author Alejandro Cabrera
 *
 * A test designed to test the behavior of your three allocation strategies.
 * This will help you ascertain that your best fit chooses the best fitting
 * block and that your worst fit chooses the worst fitting block.
 *
 * - Updates
 *   - There are now enough nodes available to satisfy all requests. 
 */
#include <iostream>
#include "../include/mm.h"

using namespace std;

static const unsigned int NODE_SIZE = sizeof(NodeType);
static const unsigned int BLOCK_CNT = 16;
static const unsigned int NODE_CNT = BLOCK_CNT + BLOCK_CNT/2;
static const unsigned int MEMORY_SIZE = (200 * NODE_SIZE);
static const unsigned int LOG_LEVEL = 10;

void
testGeneric(MemoryManager& m)
{
  void *data[BLOCK_CNT];

  // allocates BLOCK_CNT blocks of size 1, 2, ..., BLOCK_CNT
  // [1u 2u 3u 4u 5u 6u 7u 8u 9u 10u 11u 12u 13u 14u 15u 16u]
  for(size_t i = 0; i < BLOCK_CNT; ++i){
    data[i] = m.mymalloc(NODE_SIZE * (i+1));
  }
  m.printUseList();

  // free every other block
  // [1u 3u 5u 7u 9u 11u 13u 15u]
  // [2f 4f 6f 8f 10f 12f 14f 16f]
  for(size_t i = 0; i < BLOCK_CNT; i += 2){
    m.myfree(data[i]);
  }
  m.printUseList();

  // allocate BLOCK_CNT/2 blocks of size (4 * NODE_SIZE)
  // [1u 3u 5u 7u 9u 11u 13u 15u]
  // used list depends on strategy
  // you should work this out by hand
  for(size_t i = 0; i < BLOCK_CNT; i += 2){
    data[i] = m.mymalloc(NODE_SIZE * 4);
  }
  m.printUseList();

  // free everything
  for(size_t i = 0; i < BLOCK_CNT; ++i){
    m.myfree(data[i]);
  }
  m.printUseList();

  m.printMemoryStatus(LOG_LEVEL);
}

void
testWorstFit()
{
  MemoryManager m(MEMORY_SIZE, NODE_SIZE * NODE_CNT);
  m.setAllocMode(WORST_FIT);
  testGeneric(m);
}

void
testBestFit()
{
  MemoryManager m(MEMORY_SIZE, NODE_SIZE * NODE_CNT);
  m.setAllocMode(BEST_FIT);
  testGeneric(m);
}

void
testFirstFit()
{
  MemoryManager m(MEMORY_SIZE, NODE_SIZE * NODE_CNT);
  m.setAllocMode(FIRST_FIT);
  testGeneric(m);
}

int main() 
{
  cout << "=================\n"
       << "testing first fit\n"
       << "=================\n\n";
  testFirstFit();

  cout << "\n=================\n"
       << "testing best fit \n"
       << "=================\n\n";
  testBestFit();

  cout << "\n=================\n"
       << "testing worst fit\n"
       << "=================\n\n";
  testWorstFit();
  
  return 0;
}
